"use client";

import * as React from "react";

import { type DropdownMenuProps } from "@radix-ui/react-dropdown-menu";

import { MarkdownPlugin } from "@platejs/markdown";
import { ArrowDownToLineIcon } from "lucide-react";
import { createSlateEditor, serializeHtml } from "platejs";
import { useEditorRef } from "platejs/react";

import { BaseEditorKit } from "@/components/plate/editor-base-kit";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/plate/ui/dropdown-menu";

import { EditorStatic } from "./editor-static";
import { ToolbarButton } from "./toolbar";

const siteUrl = "https://platejs.org";

export function ExportToolbarButton(props: DropdownMenuProps) {
  const editor = useEditorRef();
  const [open, setOpen] = React.useState(false);

  const getCanvas = async () =&gt; {
    const { default: html2canvas } = await import("html2canvas-pro");

    const style = document.createElement("style");
    document.head.append(style);

    const canvas = await html2canvas(editor.api.toDOMNode(editor)!, {
      onclone: (document: Document) =&gt; {
        const editorElement = document.querySelector(
          '[contenteditable="true"]',
        );
        if (editorElement) {
          Array.from(editorElement.querySelectorAll("*")).forEach((element) =&gt; {
            const existingStyle = element.getAttribute("style") || "";
            element.setAttribute(
              "style",
              `${existingStyle}; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important`,
            );
          });
        }
      },
    });
    style.remove();

    return canvas;
  };

  const downloadFile = async (url: string, filename: string) =&gt; {
    const response = await fetch(url);

    const blob = await response.blob();
    const blobUrl = window.URL.createObjectURL(blob);

    const link = document.createElement("a");
    link.href = blobUrl;
    link.download = filename;
    document.body.append(link);
    link.click();
    link.remove();

    // Clean up the blob URL
    window.URL.revokeObjectURL(blobUrl);
  };

  const exportToPdf = async () =&gt; {
    const canvas = await getCanvas();

    const PDFLib = await import("pdf-lib");
    const pdfDoc = await PDFLib.PDFDocument.create();
    const page = pdfDoc.addPage([canvas.width, canvas.height]);
    const imageEmbed = await pdfDoc.embedPng(canvas.toDataURL("PNG"));
    const { height, width } = imageEmbed.scale(1);
    page.drawImage(imageEmbed, {
      height,
      width,
      x: 0,
      y: 0,
    });
    const pdfBase64 = await pdfDoc.saveAsBase64({ dataUri: true });

    await downloadFile(pdfBase64, "plate.pdf");
  };

  const exportToImage = async () =&gt; {
    const canvas = await getCanvas();
    await downloadFile(canvas.toDataURL("image/png"), "plate.png");
  };

  const exportToHtml = async () =&gt; {
    const editorStatic = createSlateEditor({
      plugins: BaseEditorKit,
      value: editor.children,
    });

    const editorHtml = await serializeHtml(editorStatic, {
      editorComponent: EditorStatic,
      props: { style: { padding: "0 calc(50% - 350px)", paddingBottom: "" } },
    });

    const tailwindCss = `&lt;link rel="stylesheet" href="${siteUrl}/tailwind.css"&gt;`;
    const katexCss = `&lt;link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.18/dist/katex.css" integrity="sha384-9PvLvaiSKCPkFKB1ZsEoTjgnJn+O3KvEwtsz37/XrkYft3DTk2gHdYvd9oWgW3tV" crossorigin="anonymous"&gt;`;

    const html = `&lt;!DOCTYPE html&gt;
    &lt;html lang="en"&gt;
      &lt;head&gt;
        &lt;meta charset="utf-8" /&gt;
        &lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&gt;
        &lt;meta name="color-scheme" content="light dark" /&gt;
        &lt;link rel="preconnect" href="https://fonts.googleapis.com" /&gt;
        &lt;link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /&gt;
        &lt;link
          href="https://fonts.googleapis.com/css2?family=Inter:wght@400..700&family=JetBrains+Mono:wght@400..700&display=swap"
          rel="stylesheet"
        /&gt;
        ${tailwindCss}
        ${katexCss}
        &lt;style&gt;
          :root {
            --font-sans: 'Inter', 'Inter Fallback';
            --font-mono: 'JetBrains Mono', 'JetBrains Mono Fallback';
          }
        &lt;/style&gt;
      &lt;/head&gt;
      &lt;body&gt;
        ${editorHtml}
      &lt;/body&gt;
    &lt;/html&gt;`;

    const url = `data:text/html;charset=utf-8,${encodeURIComponent(html)}`;

    await downloadFile(url, "plate.html");
  };

  const exportToMarkdown = async () =&gt; {
    const md = editor.getApi(MarkdownPlugin).markdown.serialize();
    const url = `data:text/markdown;charset=utf-8,${encodeURIComponent(md)}`;
    await downloadFile(url, "plate.md");
  };

  return (
    &lt;DropdownMenu open={open} onOpenChange={setOpen} modal={false} {...props}&gt;
      &lt;DropdownMenuTrigger asChild&gt;
        &lt;ToolbarButton pressed={open} tooltip="Export" isDropdown&gt;
          &lt;ArrowDownToLineIcon className="size-4" /&gt;
        &lt;/ToolbarButton&gt;
      &lt;/DropdownMenuTrigger&gt;

      &lt;DropdownMenuContent align="start"&gt;
        &lt;DropdownMenuGroup&gt;
          &lt;DropdownMenuItem onSelect={exportToHtml}&gt;
            Export as HTML
          &lt;/DropdownMenuItem&gt;
          &lt;DropdownMenuItem onSelect={exportToPdf}&gt;
            Export as PDF
          &lt;/DropdownMenuItem&gt;
          &lt;DropdownMenuItem onSelect={exportToImage}&gt;
            Export as Image
          &lt;/DropdownMenuItem&gt;
          &lt;DropdownMenuItem onSelect={exportToMarkdown}&gt;
            Export as Markdown
          &lt;/DropdownMenuItem&gt;
        &lt;/DropdownMenuGroup&gt;
      &lt;/DropdownMenuContent&gt;
    &lt;/DropdownMenu&gt;
  );
}
